import asyncio
import time

from bilibili_api import live, Credential


class MultiRoomMonitor:
    def __init__(self, credential=None, redis_mgr=None):
        self.credential = credential or Credential()
        self.redis_mgr = redis_mgr
        self.rooms = {}  # {room_id: LiveDanmaku实例}
        self.tasks = {}  # {room_id: 异步任务}
        self.lock = asyncio.Lock()
        self._running = False

    async def _connect_room(self, room: live.LiveDanmaku):
        """单个房间连接协程"""
        room_id = room.room_display_id  # 获取房间号

        # 注册通用事件处理器
        @room.on('DANMU_MSG')
        async def on_danmaku(event):
            formatted_data = self._format_danmu(event)
            print(f"[房间{room_id}] 弹幕：{event['data']['info'][1]}")
            # 新增 Redis 推送
            if self.redis_mgr:
                await self.redis_mgr.push_data(
                    "STREAM:DANMAKU",
                    formatted_data
                )
        @room.on('SEND_GIFT')
        async def on_gift(event):
            print(f"[房间{room_id}] 礼物：{event}")

        @room.on('ONLINE_RANK_COUNT')
        async def on_online_rank(event):
            formatted_data = self._format_online_rank(event, room_id)
            if self.redis_mgr:
                await self.redis_mgr.push_data(
                    "STREAM:ONLINE_RANK",
                    formatted_data
                )

        await room.connect()

    # 新增数据格式化方法
    def _format_danmu(self, event) -> dict:
        medal_level = -1
        medal_name = ''
        medal_from_user = ''
        medal_from_uid = -1
        honor_level = event['data']['info'][16][0] if(len(event['data']['info'][16]))>0 else -1
        guard_level = event['data']['info'][0][15]['user']['medal']['guard_level'] if(event['data']['info'][0][15]['user']['medal'] != None) else -1
        if(len(event['data']['info'][3]) > 0):
            medal_level = event['data']['info'][3][0]
            medal_name = event['data']['info'][3][1]
            medal_from_user = event['data']['info'][3][2]
            medal_from_uid = event['data']['info'][3][12]
        return {
            'danmu_user': event['data']['info'][2][1],  # 用户名
            'uid': event['data']['info'][2][0],
            'content': event['data']['info'][1],        # 弹幕内容
            'danmu_time': event['data']['info'][9]['ts'],  # 原始时间戳（毫秒）
            'medal_level': medal_level,
            'medal_name': medal_name,
            'medal_from_user': medal_from_user,
            'medal_from_uid': medal_from_uid,
            'honor_level': honor_level,
            'guard_level': guard_level,
            "room_real_id": event['room_display_id'],
            'create_time': int(time.time() * 1000)
        }

    def _format_online_rank(self, event, room_id) -> dict:
        """格式化在线人数数据"""
        return {
            'online_count': event["data"]["data"]["online_count"],
            'room_real_id': event['room_real_id'],
            'create_time': int(time.time() * 1000)
        }


    async def add_room(self, room_id):
        """动态添加房间"""
        async with self.lock:
            if room_id in self.rooms:
                return

            room = live.LiveDanmaku(room_id, credential=self.credential)
            task = asyncio.create_task(self._connect_room(room))

            self.rooms[room_id] = room
            self.tasks[room_id] = task

    async def remove_room(self, room_id):
        """公共移除方法（带锁）"""
        async with self.lock:
            await self._remove_room(room_id)

    async def _remove_room(self, room_id):
        """内部移除逻辑（假设已持有锁）"""
        if room_id not in self.rooms:
            return

        room = self.rooms.pop(room_id)
        task = self.tasks.pop(room_id)

        await room.disconnect()
        task.cancel()
        try:
            await task
        except asyncio.CancelledError:
            pass

    async def start(self, initial_rooms:list):
        """启动监听服务"""
        self._running = True
        # 批量添加初始房间
        for room_id in initial_rooms:
            await self.add_room(room_id)
            await asyncio.sleep(1)

        # 保持主循环运行 当主协程没有持续任务时，事件循环会因无任务可执行而自动退出
        while self._running:
            await asyncio.sleep(1)

    async def stop(self):
        """停止所有监听"""
        if not self._running:
            return
        self._running = False
        async with self.lock:
            for room_id in list(self.rooms.keys()):
                await self._remove_room(room_id)

# if __name__ == "__main__":
#     # 初始化凭据（需要已登录的cookie）
#     credential = Credential(
#         sessdata="6b1a13d7%2C1758939876%2C8951f%2A31CjCnuNCNztCftrPkFjag8k47dIuQZ-ut62XXcemFADFMuB25dQCJqC6nM4LKkTq7fpYSVlo0ZFNkVmVXcWhlcXhXS3hCOXZBYjYyVXdJZ0ZSNllfWFJ3T3VBZEVfUkxxNFJrNU4xd1BZNVAxcEVOc3JFUUNubV8tc045c0ZsaXR2NkMtVjFQZU1nIIEC",
#         bili_jct="0fe3dcb51de2f49bea0458875ba9c957",
#         buvid3="21386F8E-E6CB-6015-D6CB-63F5C751BB9751434infoc",
#         dedeuserid="3546869426817357")
#
#     # 要监听的房间列表
#     room_ids = [1871971925]
#
#     async def main():
#         monitor = MultiRoomMonitor(credential)
#         try:
#             await monitor.start(room_ids)
#         except KeyboardInterrupt:
#             await monitor.stop()
#
#     # 启动异步事件循环
#     asyncio.run(main())